package com.spring.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * 可以考虑把所有公共的方法都写在baseDAo中，这个时候，让所有的DAO都继承BaseDao
 * 这样基本上就实现了大量的基础方法，如果DAO中有一些特殊的方法，再在具体的实现类的
 *
 * @param <T>
 */
@Repository("baseDao")
public class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T> {
    @Resource(name = "sessionFactory")
    public void setSuperSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    //获取Session
    protected Session getSession() {
        return this.getHibernateTemplate().getSessionFactory().getCurrentSession();
    }

    /**
     * 创建一个Class的对象来获取泛型的class
     */
    private Class<T> cls;

    public Class<T> getCls() {
        //获取泛型的Class对象
        if (cls == null)
            return ((Class<T>)
                    (((ParameterizedType) (this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
        return cls;
    }

    @Override
    public void add(T t) {
        this.getHibernateTemplate().save(t);
    }

    @Override
    public void update(T t) {
        this.getHibernateTemplate().update(t);
    }

    @Override
    public void delete(int id) {
        this.getHibernateTemplate().delete(this.load(id));
    }

    @Override
    public T load(int id) {
      //  System.out.println("BaseDao" + getCls().getName());
//    return this.getHibernateTemplate().load(getCls(), id);
    return this.getHibernateTemplate().get(getCls(), id);
    }

    @Override
    public List<T> list(String hql, Object[] args) {
        Query<T> query = this.getSession().createQuery(hql);
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                query.setParameter(i, args[i]);
            }
        }
        List<T> list = query.list();
        return list;
    }

    @Override
    public List<T> list(String hql) {
        return this.list(hql, null);
    }

    @Override
    public List<T> list(String hql, Object arg) {
        return this.list(hql, new Object[]{arg});
    }
}
